﻿using HirelSeriesH.Tools;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace HirelSeriesH.Entity
{
    public class PLC_XINJE
    {
        public SerialPort serial = null;

        public readonly object locker = new object();
        public PLC_XINJE(SerialPort sp)
        {
            serial = sp;
        }
        public byte[] SendCMD(byte[] CMD)
        {
            if (serial == null)
            {
                return null;
            }
            if (!serial.IsOpen)
            {
                serial.Open();
            }

            lock (new object())
            {
                serial.DiscardInBuffer();
                serial.Write(CMD, 0, CMD.Length);
                Thread.Sleep(30);
                int bytes = serial.BytesToRead;
                //for (int i = 0; i < 20; i++)
                //{
                //    Thread.Sleep(5);
                //    bytes = serial.BytesToRead;
                //    if (bytes == 6 || bytes == 8) break;
                //}
                byte[] tempBuffer = new byte[bytes];
                serial.Read(tempBuffer, 0, bytes);

                //if (!tempBuffer.SequenceEqual(CMD))  //重发
                //{
                //    serial.DiscardInBuffer();
                //    serial.Write(CMD, 0, CMD.Length);
                //    bytes = 0;
                //    for (int i = 0; i < 20; i++)
                //    {
                //        Thread.Sleep(5);
                //        bytes = serial.BytesToRead;
                //        if (bytes == 6 || bytes == 8) break;
                //    }
                //    tempBuffer = new byte[bytes];
                //    serial.Read(tempBuffer, 0, bytes);
                //}

                return tempBuffer;
            }
        }
        /// <summary>
        /// 吸合/断开1个端口
        /// </summary>
        /// <param name="PortNum">端口：0~17</param>
        /// <param name="isOnOff">吸合/断开</param>
        public void SetDO(byte PortNum, bool isOnOff)
        {
            lock (locker)
            {
                byte[] cmd = new byte[] { 0x01, 0x05, 0x60, 0x00, 0x00, 0x00 };
                if (PortNum >= 16)
                {
                    cmd[2] = 0x61;
                    PortNum = (byte)(PortNum - 16);
                }
                cmd[3] = PortNum;
                if (isOnOff) cmd[4] = 0xFF;
                var CMD = CheckWorker.ModbusCRC16(cmd);
                var rps = SendCMD(CMD);
            }
        }
        /// <summary>
        /// 1次设置16个端口状态
        /// </summary>
        /// <param name="bLow">低位字节</param>
        /// <param name="bHigh">高位字节</param>
        public void SetDO16(byte bLow, byte bHigh)
        {
            byte[] cmd = new byte[] { 0x01, 0x0F, 0x60, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00 };
            cmd[7] = bLow;
            cmd[8] = bHigh;
            var CMD = CheckWorker.ModbusCRC16(cmd);
            var rps = SendCMD(CMD);
        }
        /// <summary>
        /// 吸合/断开多个端口
        /// </summary>
        /// <param name="bStart">开始地址：0~15</param>
        /// <param name="bCount">端口数量：1~8</param>
        /// <param name="bData">开关状态数据(1个字节)</param>
        public void SetDO(byte bStart, byte bCount, byte bData)
        {
            byte[] cmd = new byte[] { 0x01, 0x0F, 0x60, 0x00, 0x00, 0x10, 0x01, 0x00 };
            cmd[3] = bStart;
            cmd[5] = bCount;
            cmd[7] = bData;
            var CMD = CheckWorker.ModbusCRC16(cmd);
            var rps = SendCMD(CMD);
        }

        /// <summary>
        /// 构造PLC状态串命令
        /// </summary>
        /// <param name="iArea">测试区：1~2</param>
        /// <param name="state">状态串"00000000"</param>
        /// <returns></returns>
        public bool SetState(int iArea, string state)
        {
            if (string.IsNullOrEmpty(state)) return false;
            if (state.Length != 8) return false;

            byte bData = (byte)Convert.ToInt32(state, 2);

            byte iStart = 0;
            byte iCount = 6;
            if (iArea == 1)
            {
                iStart = 0;
            }
            else
            {
                iStart = 6;
            }

            SetDO(iStart, iCount, bData);

            //byte[] cmd = MakeReadCMD(byte1);
            //if ((DateTime.Now - LastUpdateTime).TotalMilliseconds < 200)//距上一次发命令小于200ms则等待200ms再发
            //{
            //    Thread.Sleep(200);
            //    //TextLog.TextLogHelper.WriteLog("PLC_VG_PN 串口IO 延时200ms");
            //}
            //byte[] rps = SendCMD(cmd);
            //VG_State = state;
            //LastUpdateTime = DateTime.Now;
            //if (!Enumerable.SequenceEqual(cmd, rps)) return false;

            return true;
        }
    }
}
